/*
 * Cirrus EP7312 Intererrupt handler
 *
 * Copyright (c) 2002 by Jay Monkman <jtm@smoothsmoothie.com>
 *
 * Copyright (c) 2002 by Charlie Steader <charlies@poliac.com>
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *
 *  http://www.rtems.com/license/LICENSE.
 *
 *
 *  $Id: bsp_irq_asm.S,v 1.3 2004/04/21 10:42:43 ralf Exp $
*/
#define __asm__
#include "irq.h"

#define VECTOR_TABLE 0x40

/*
 * Function to obtain, execute an IT handler and acknowledge the IT
 */

	.globl ExecuteITHandler
ExecuteITHandler :
/*
 * Look at interrupt status register to determine source.
 * From source, determine offset into expanded vector table
 * and load handler address into r0.
 */

  ldr   r1, =0x80000000 /* close to interrupt status/mask registers 1 */
  ldr   r2, =0x80001000 /* close to interrupt status/mask registers 2 */
  ldr   r3, =0x80002000 /* close to interrupt status/mask registers 3 */

  stmdb	  sp!,{r4, r5, r6}

/*
 * INTSR3
 */
check_dai:
  ldr   r4, [r3, #0x240]
  ldr   r5, [r3, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
  tst   r6, #0x0001
  beq   check_extfiq
  ldr	r0, =(VECTOR_TABLE + (4 * 21)) /* load the vector number */
  b     get_handler

/*
 * INTSR1
 */
check_extfiq:
  ldr   r4, [r1, #0x240]
  ldr   r5, [r1, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
  tst   r6, #0x0001
  beq   check_bl
  ldr	r0, =(VECTOR_TABLE + (4 * 0)) /* load the vector number */
  b     get_handler

check_bl:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r1, #0x240]
  ldr   r5, [r1, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x0002
  beq   check_we
  ldr	r0, =(VECTOR_TABLE + (4 * 1)) /* load the vector number */
  b     get_handler

check_we:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r1, #0x240]
  ldr   r5, [r1, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x0004
  beq   check_mc
  ldr	r0, =(VECTOR_TABLE + (4 * 2)) /* load the vector number */
  b     get_handler

check_mc:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r1, #0x240]
  ldr   r5, [r1, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x0008
  beq   check_cs
  ldr	r0, =(VECTOR_TABLE + (4 * 3)) /* load the vector number */
  b     get_handler

check_cs:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r1, #0x240]
  ldr   r5, [r1, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x0010
  beq   check_e1
  ldr	r0, =(VECTOR_TABLE + (4 * 4)) /* load the vector number */
  b     get_handler

check_e1:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r1, #0x240]
  ldr   r5, [r1, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x0020
  beq   check_e2
  ldr	r0, =(VECTOR_TABLE + (4 * 5)) /* load the vector number */
  b     get_handler

check_e2:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r1, #0x240]
  ldr   r5, [r1, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x0040
  beq   check_e3
  ldr	r0, =(VECTOR_TABLE + (4 * 6)) /* load the vector number */
  b     get_handler

check_e3:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r1, #0x240]
  ldr   r5, [r1, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x0080
  beq   check_tc1
  ldr	r0, =(VECTOR_TABLE + (4 * 7)) /* load the vector number */
  b     get_handler

check_tc1:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r1, #0x240]
  ldr   r5, [r1, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x0100
  beq   check_tc2
  ldr	r0, =(VECTOR_TABLE + (4 * 8)) /* load the vector number */
  b     get_handler

check_tc2:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r1, #0x240]
  ldr   r5, [r1, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x0200
  beq   check_rtc
  ldr	r0, =(VECTOR_TABLE + (4 * 9)) /* load the vector number */
  b     get_handler

check_rtc:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r1, #0x240]
  ldr   r5, [r1, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x0400
  beq   check_tick
  ldr	r0, =(VECTOR_TABLE + (4 * 10)) /* load the vector number */
  b     get_handler

check_tick:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r1, #0x240]
  ldr   r5, [r1, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x0800
  beq   check_utx1
  ldr	r0, =(VECTOR_TABLE + (4 * 11)) /* load the vector number */
  b     get_handler

check_utx1:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r1, #0x240]
  ldr   r5, [r1, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x1000
  beq   check_urx1
  ldr	r0, =(VECTOR_TABLE + (4 * 12)) /* load the vector number */
  b     get_handler

check_urx1:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r1, #0x240]
  ldr   r5, [r1, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x2000
  beq   check_ums
  ldr	r0, =(VECTOR_TABLE + (4 * 13)) /* load the vector number */
  b     get_handler

check_ums:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r1, #0x240]
  ldr   r5, [r1, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x4000
  beq   check_sse
  ldr	r0, =(VECTOR_TABLE + (4 * 14)) /* load the vector number */
  b     get_handler

check_sse:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r1, #0x240]
  ldr   r5, [r1, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x8000
  beq   check_kbd
  ldr	r0, =(VECTOR_TABLE + (4 * 15)) /* load the vector number */
  b     get_handler

/*
 * INTSR2
 */
check_kbd:
  ldr   r4, [r2, #0x240]
  ldr   r5, [r2, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
  tst   r6, #0x0001
  beq   check_ss2rx
  ldr	r0, =(VECTOR_TABLE + (4 * 16)) /* load the vector number */
  b     get_handler

check_ss2rx:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r2, #0x240]
  ldr   r5, [r2, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x0002
  beq   check_ss2tx
  ldr	r0, =(VECTOR_TABLE + (4 * 17)) /* load the vector number */
  b     get_handler

check_ss2tx:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r2, #0x240]
  ldr   r5, [r2, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x0004
  beq   check_utx2
  ldr	r0, =(VECTOR_TABLE + (4 * 18)) /* load the vector number */
  b     get_handler

check_utx2:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r2, #0x240]
  ldr   r5, [r2, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x1000
  beq   check_urx2
  ldr	r0, =(VECTOR_TABLE + (4 * 19)) /* load the vector number */
  b     get_handler

check_urx2:
#if 0
MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
  ldr   r4, [r2, #0x240]
  ldr   r5, [r2, #0x280]
  and   r6, r4, r5 /* only look at interrupts which are enabled */
#endif
  tst   r6, #0x2000
  beq   IRQ_NoInterrupt
  ldr	r0, =(VECTOR_TABLE + (4 * 20)) /* load the vector number */
  b     get_handler

get_handler:

  ldmia	  sp!,{r4, r5, r6}

  ldr	r0, [r0]		/* extract the IT handler @ */

  /*
   * re-enable interrupts at processor level as the current
   * interrupt source is now masked via VEGA logic
   */
/*
  mrs	r1, cpsr
  and	r1, r1, #0xFFFFFF3F
  msr	cpsr, r1
*/

  stmdb	  sp!,{lr}
  ldr     lr, =IRQ_return         /* prepare the return from handler  */

  mov     pc, r0			/* EXECUTE INT HANDLER */

IRQ_return:
  ldmia sp!,{lr}

IRQ_NoInterrupt:
  /* return to the "main" interrupt handler */
  mov pc, lr
